package com.lagou.client;

import com.lagou.entity.JSONSerializer;
import com.lagou.entity.RpcDecoder;
import com.lagou.entity.RpcEncoder;
import com.lagou.entity.RpcRequest;
import com.lagou.handler.CommonHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 消费者
 */
public class RPCConsumer {

    private String host;
    private Integer port;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }

    //1.创建一个线程池对象  -- 它要处理我们自定义事件
    private ExecutorService executorService =
            Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    //2.声明一个自定义事件处理器  CommonHandler
    private CommonHandler commonHandler;

    private ChannelFuture channelFuture;

    private ChannelPipeline pipeline;


    public RPCConsumer(String host,Integer port,CommonHandler commonHandler){
        this.host = host;
        this.port = port;
        this.commonHandler = commonHandler;
        try {
            initClient();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void setHandler(CommonHandler commonHandler){
        //添加自定义事件处理器
        this.commonHandler = commonHandler;
        pipeline.addLast(commonHandler);
    }


    //3.编写方法,初始化客户端  ( 创建连接池  bootStrap  设置bootstrap  连接服务器)
    public void initClient() throws InterruptedException {
        //1) 初始化UserClientHandler
        //2)创建连接池对象
        EventLoopGroup group = new NioEventLoopGroup();
        //3)创建客户端的引导对象
        Bootstrap bootstrap =  new Bootstrap();
        //4)配置启动引导对象
        bootstrap.group(group)
                //设置通道为NIO
                .channel(NioSocketChannel.class)
                //设置请求协议为TCP
                .option(ChannelOption.TCP_NODELAY,true)
                //监听channel 并初始化
                .handler(new ChannelInitializer<SocketChannel>() {
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        //获取ChannelPipeline
                        pipeline = socketChannel.pipeline();
                        //设置编码
                        pipeline.addLast(new RpcDecoder(RpcRequest.class,new JSONSerializer()));
                        pipeline.addLast(new RpcEncoder(RpcRequest.class,new JSONSerializer()));
                        pipeline.addLast(commonHandler);
                    }
                });

        //5)连接服务端
        channelFuture = bootstrap.connect(this.host, this.port).sync();
        System.out.println("连接服务端成功：" + this.host + ":" + this.port);
    }

    public void close() {
        try {
            channelFuture.channel().close();
            System.out.println("成功断开连接：" + this.host + ":" + this.port);
        }catch (Exception e){
            System.out.println("断开连接失败：" + this.host + ":" + this.port);
            e.printStackTrace();
        }finally {
            commonHandler.disconnect();
        }
    }


    public Object call(RpcRequest rpcRequest) throws Exception{
        commonHandler.setParam(rpcRequest);


        rpcRequest.setRequestTimeStamp(System.currentTimeMillis());
        //3).使用线程池,开启一个线程处理处理call() 写操作,并返回结果
        Object result = executorService.submit(commonHandler).get();

        //4)return 结果
        return result;
    }

}
